package mysql

import (
	"database/sql"
	"duanju-mq/pkg/config"
	"duanju-mq/pkg/log"
	"github.com/go-sql-driver/mysql"
	"strconv"
	"strings"
)

type DB struct {
	*sql.DB
}

var defaultConnPool = config.Int("lib.mysql.default.connpool", 10, "mysql默认连接池大小，0为不限")

func FromConfig(key string) *DB {
	db, err := Open(
		*config.String(key+".addr", "127.0.0.1:3306", ""),
		*config.String(key+".user", "", ""),
		*config.String(key+".pwd", "", ""),
		*config.String(key+".name", "", ""),
	)
	if err != nil {
		log.Fatal(err)
	}
	return db
}

func Open(addr, user, pwd, name string) (*DB, error) {
	db, err := sql.Open("mysql", user+":"+pwd+"@tcp("+addr+")/"+name+"?charset=utf8mb4,utf8")
	if err != nil {
		return nil, err
	}
	return New(db), nil
}

func New(db *sql.DB) *DB {
	d := &DB{db}
	if n := *defaultConnPool; n > 0 {
		d.SetConnPool(n)
	}
	return d
}

func (d *DB) SetConnPool(n int) {
	d.SetMaxOpenConns(n)
	d.SetMaxIdleConns(n)
}

func SetDefaultConnPool(n int) {
	*defaultConnPool = n
}

const (
	ErrDuplicateEntry = 1062
	ErrNoSuchTable    = 1146
)

func IsErr(err error, errcode int) bool {
	if e, ok := err.(*mysql.MySQLError); ok {
		return int(e.Number) == errcode
	}
	if strings.HasPrefix(err.Error(), "Error "+strconv.Itoa(errcode)+":") {
		return true
	}
	return false
}

type Tx struct {
	*sql.Tx
}

func (db *DB) Transaction(f func(*Tx) error) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}
	if err := f(&Tx{tx}); err != nil {
		tx.Rollback()
		return err
	}
	return tx.Commit()
}

func (tx *Tx) Rollback() error { return nil }
func (tx *Tx) Commit() error   { return nil }
